/******************************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Ltd.                       */
/*                                                                            */
/*  NAME      = informix_common.c                                             */
/*  NOTE      = TDS 请求解析                                                  */
/*  DATE      = 2015/08/26 by zhengxd                                         */
/******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include <stdint.h>
#include <limits.h>

#include "informix_common.h"

#define INFORMIX_REPORT_KEY_DBNAME     APM_REPORT_KEY_SESSION".informix.dbname"

/*******************************************************************************
*  FUNC     :  释放内存
*  ARGS     :  pp_buffer
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void informix_free(char **pp_buffer)
{
    if (pp_buffer == NULL || *pp_buffer == NULL)
    {
        return;
    }

    frfree(*pp_buffer);
    *pp_buffer = NULL;
    return;
}

/*******************************************************************************
*  FUNC     :  初始化分片包信息
*  ARGS     :  pp_st_fragment (分片包信息)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void informix_init_fragment(L7_fragment_informix *p_st_fragment)
{
    if (p_st_fragment == NULL)
    {
        return;
    }

    if (p_st_fragment->p_st_data)
    {
        bytebuff_free(&p_st_fragment->p_st_data);
    }
    memset(p_st_fragment, 0x0, sizeof(L7_fragment_informix));
    p_st_fragment->i_need_req_resp = INFORMIX_DIRECT_REQUEST;

    return;
}

/*******************************************************************************
*  FUNC     :  初始化分片包信息
*  ARGS     :  pp_st_fragment (分片包信息)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void informix_destroy_fragment(L7_fragment_informix **pp_st_fragment)
{
    if (pp_st_fragment == NULL || *pp_st_fragment == NULL)
    {
        return;
    }

    L7_fragment_informix *p_st_fragment = *pp_st_fragment;

    if (p_st_fragment->p_st_data)
    {
        bytebuff_free(&p_st_fragment->p_st_data);
    }

    frfree(p_st_fragment);
    *pp_st_fragment = NULL;
    return;
}

/*******************************************************************************
*  FUNC     :  做成request
*  ARGS     :  void
*  RTN      :  非NULL       (normal)
*              NULL         (error)
*  NOTE     :
*******************************************************************************/
L7_req_informix* informix_create_request(void)
{
    L7_req_informix *p_st_req = NULL;

    /* 申请request */
    p_st_req = (L7_req_informix *)frmalloc(sizeof(L7_req_informix));
    if (p_st_req == NULL)
    {
        return NULL;
    }
    /* 初始化 */
    memset(p_st_req, 0x0, sizeof(L7_req_informix));
    p_st_req->i_add_bind_flg = FR_YES;

    return p_st_req;
}

/*******************************************************************************
*  FUNC     :  销毁session信息
*  ARGS     :  pp_st_sess(session信息)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void informix_destroy_session(L7session_informix **pp_st_sess)
{
    if(pp_st_sess == NULL || *pp_st_sess == NULL)
    {
        return;
    }

    L7session_informix *p_st_sess = *pp_st_sess;

    if (p_st_sess->p_cli_host_user)
    {
        frfree(p_st_sess->p_cli_host_user);
    }
    if (p_st_sess->p_program)
    {
        frfree(p_st_sess->p_program);
    }
    if (p_st_sess->p_db_name)
    {
        frfree(p_st_sess->p_db_name);
    }
    if (p_st_sess->p_db_user)
    {
        frfree(p_st_sess->p_db_user);
    }
    if (p_st_sess->p_req_ver)
    {
        frfree(p_st_sess->p_req_ver);
    }

    frfree(p_st_sess);
    *pp_st_sess = NULL;
    return;
}

/*******************************************************************************
*  FUNC     :  request信息初始化
*  ARGS     :  pp_st_request(request信息)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void informix_int_request(L7_req_informix *p_st_req)
{
    if(p_st_req == NULL )
    {
        return;
    }

    if (p_st_req->p_sql)
    {
        frfree(p_st_req->p_sql);
    }
    if (p_st_req->i_new_statement == FR_YES)
    {
        /* 释放SQL statement信息 */
        frdb_statement_free(&(p_st_req->p_st_statement));
    }
    memset(p_st_req, 0x0, sizeof(L7_req_informix));
    p_st_req->i_add_bind_flg = FR_YES;

    return;
}

/*******************************************************************************
*  FUNC     :  request信息释放
*  ARGS     :  pp_st_req(request信息)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void informix_destroy_request(L7_req_informix **pp_st_req)
{
    if(pp_st_req == NULL || *pp_st_req == NULL)
    {
        return;
    }

    L7_req_informix *p_st_req = *pp_st_req;

    if (p_st_req->p_sql)
    {
        frfree(p_st_req->p_sql);
    }
    if (p_st_req->i_new_statement == FR_YES)
    {
        /* 释放SQL statement信息 */
        frdb_statement_free(&(p_st_req->p_st_statement));
    }

    frfree(p_st_req);
    *pp_st_req = NULL;
    return;
}

/*******************************************************************************
*  FUNC     :  response信息释放
*  ARGS     :  pp_st_request(request信息)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void informix_int_response(L7_resp_informix *p_st_resp)
{
    if(p_st_resp == NULL)
    {
        return;
    }

    if (p_st_resp->p_error_msg)
    {
        frfree(p_st_resp->p_error_msg);
    }
    frlist_remove_all(&p_st_resp->st_metadata_column, frdb_metadata_node_free);
    memset(p_st_resp, 0x0, sizeof(L7_resp_informix));

    return;
}

/*******************************************************************************
*  FUNC     :  response信息释放
*  ARGS     :  pp_st_request(request信息)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void informix_destroy_response(L7_resp_informix **pp_st_resp)
{
    if(pp_st_resp == NULL || *pp_st_resp == NULL)
    {
        return;
    }

    L7_resp_informix *p_st_resp = *pp_st_resp;

    if (p_st_resp->p_error_msg)
    {
        frfree(p_st_resp->p_error_msg);
    }
    frlist_remove_all(&p_st_resp->st_metadata_column, frdb_metadata_node_free);

    frfree(p_st_resp);
    *pp_st_resp = NULL;
    return;
}

/*******************************************************************************
*  FUNC     :  初始化私有SQL Server session
*  ARGS     :  p_st_private(私有session数据)
*  RTN      :  FR_SUCC       (normal)
*              FR_FAIL       (error)
*  NOTE     :  p_st_private必须不是NULL
*******************************************************************************/
void informix_destroy_curr_info(L7session_informix_private *p_st_private)
{
    if (p_st_private->p_st_req)
    {
        informix_destroy_request(&p_st_private->p_st_req);
    }
    if (p_st_private->p_st_resp)
    {
        informix_destroy_response(&p_st_private->p_st_resp);
    }
    informix_init_fragment(p_st_private->p_st_fragment);

    return;
}

/*******************************************************************************
*  FUNC     :  根据session创建session data列表
*  ARGS     :  p_st_conn (CT信息)
*           :  p_st_session (informix session信息)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_session必须不为NULL
*******************************************************************************/
Frreport_body_data* informix_new_report_body(Conntrack *p_st_conn
                                            , L7session_informix *p_st_sess)
{
    int i_ret = FR_SUCC;
    Frreport_body_data *p_st_sess_body = NULL;

    /* 创建report body */
    p_st_sess_body = frreport_body_new_l7(p_st_conn);
    if (p_st_sess_body == NULL)
    {
        return NULL;
    }
    /* 追加connection相关信息 */
    i_ret = frreport_body_l7_add_connInfo(p_st_sess_body, p_st_conn);
    if (i_ret != FR_SUCC)
    {
        frreport_body_free(&p_st_sess_body);
        return NULL;
    }

    /* add server */
    if (p_st_sess->p_program)
    {
        i_ret = frreport_body_l7_add_str(p_st_sess_body
                                         , APM_REPORT_KEY_SESSION_SERVER
                                         , p_st_sess->p_program);
        if (i_ret != FR_SUCC)
        {
            frreport_body_free(&p_st_sess_body);
            return NULL;
        }
    }
    /* add username */
    if (p_st_sess->p_db_user)
    {
        i_ret = frreport_body_l7_add_str(p_st_sess_body
                                         , APM_REPORT_KEY_SESSION_USERNAME
                                         , p_st_sess->p_db_user);
        if (i_ret != FR_SUCC)
        {
            frreport_body_free(&p_st_sess_body);
            return NULL;
        }
    }
    /* add dbname */
    if (p_st_sess->p_db_name)
    {
        i_ret = frreport_body_l7_add_str(p_st_sess_body
                                         , INFORMIX_REPORT_KEY_DBNAME
                                         , p_st_sess->p_db_name);
        if (i_ret != FR_SUCC)
        {
            frreport_body_free(&p_st_sess_body);
            return NULL;
        }
    }
    if (p_st_sess->st_login.tv_sec != 0
        || p_st_sess->st_login.tv_usec != 0)
    {
        /* add request start time */
        i_ret = frreport_body_l7_add_timeval(p_st_sess_body
                                            , APM_REPORT_KEY_SESSION_LOGIN_TIMESTAMP
                                            , &p_st_sess->st_login);
        if (i_ret != FR_SUCC)
        {
            frreport_body_free(&p_st_sess_body);
            return NULL;
        }
    }

    return p_st_sess_body;
}

/*******************************************************************************
*  FUNC     :  合并字符串
*  ARGS     :  p_first_str(第一个字符串)
*           :  p_second_str(第二个字符串)
*           :  pp_merge_str(合并字符串)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int informix_merge_string(char *p_first_str
                         , char *p_second_str
                         , char **pp_merge_str)
{
    unsigned int ui_len = 0;
    char *p_merge_str = NULL;

    if (p_first_str == NULL)
    {
        *pp_merge_str = p_second_str;
        return APM_L7_ANALYZE_SUCC;
    }
    else if (p_second_str == NULL)
    {
        return APM_L7_ANALYZE_SUCC;
    }

    /* 第一个1指的是分隔符[;], 第二个1为了存储字符串结束符[\0] */
    ui_len = strlen(p_first_str) + 1 + strlen(p_second_str) + 1;
    p_merge_str = (char *)frmalloc(ui_len);
    if (p_merge_str == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    snprintf(p_merge_str, ui_len, "%s;%s", p_first_str, p_second_str);
    frfree(p_first_str);
    frfree(p_second_str);

    *pp_merge_str = p_merge_str;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  取得chars
*  ARGS     :  p_st_data(bytebuff信息)
*           :  i_get_flg (是否需要取出数据)
*           :  pp_output (出力数据内容)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*  RTN      :  APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int informix_read_chars(Frbyte_Packet *p_st_data
                        , int i_get_flg
                        , char **pp_output)
{
    int i_ret = FR_SUCC;
    unsigned int ui_end_word = 0;
    uint16_t u16_len = 0;
    unsigned int ui_length = 0;
    char *p_output = NULL;
    char *p_output_tmp = NULL;

    if (bytebuff_remaining(p_st_data) < 2)
    {
        return APM_L7_ANALYZE_TODO;
    }
    /* 取得长度 */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    ui_length = u16_len;

    /* 根据java反编译结合数据包, 假如长度位奇数则数据后有一位附加字节 */
    if (ui_length & 0x01)
    {
        ui_end_word = 1;
    }

    /* 判断数据是长度否足够 */
    if (ui_length + ui_end_word > (unsigned int)bytebuff_remaining(p_st_data))
    {
        return APM_L7_ANALYZE_TODO;
    }

    /* 取得数据 */
    if (i_get_flg == FR_YES)
    {
        p_output = (char *)frmalloc(ui_length + 1);
        if (p_output == NULL)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        i_ret = bytebuff_get_bytes(p_st_data, p_output, ui_length);
        if (i_ret != FR_SUCC)
        {
            frfree(p_output);
            return APM_L7_ANALYZE_FAIL;
        }
        p_output[ui_length] = '\0';
        /* 跳过数据后的一位附加字节 */
        if (ui_end_word)
        {
            i_ret = bytebuff_skip(p_st_data, 1);
            if (i_ret != FR_SUCC)
            {
                frfree(p_output);
                return APM_L7_ANALYZE_FAIL;
            }
        }
    }
    /* 跳过数据位 */
    else
    {
        i_ret = bytebuff_skip(p_st_data, ui_length + ui_end_word);
        if (i_ret != FR_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        return APM_L7_ANALYZE_SUCC;
    }

    /* 设置出力返回 */
    if (*pp_output)
    {
        ui_length += strlen(*pp_output) + 1 + 1;
        p_output_tmp = (char *)frmalloc(ui_length);
        if (p_output_tmp == NULL)
        {
            frfree(p_output);
            return APM_L7_ANALYZE_FAIL;
        }
        snprintf(p_output_tmp, ui_length, "%s,%s", *pp_output, p_output);
        frfree(*pp_output);
        frfree(p_output);
        *pp_output = p_output_tmp;
    }
    else
    {
        *pp_output = p_output;
    }
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  取得padded
*  ARGS     :  p_st_data(bytebuff信息)
*           :  ui_length (要取得数据位的长度)
*           :  pp_output (出力数据内容)
*           :  p_ui_out_size (出力数据内容size)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*  RTN      :  APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int informix_read_padded(Frbyte_Packet *p_st_data
                        , unsigned int ui_length
                        , char **pp_output
                        , unsigned int *p_ui_out_size)
{
    int i_ret = FR_SUCC;
    unsigned int ui_end_word = 0;
    char *p_output = NULL;

    /* 根据java反编译结合数据包, 假如长度位奇数则数据后有一位附加字节 */
    if (ui_length & 0x01)
    {
        ui_end_word = 1;
    }

    /* 判断数据是长度否足够 */
    if (ui_length + ui_end_word > (unsigned int)bytebuff_remaining(p_st_data))
    {
        return APM_L7_ANALYZE_TODO;
    }

    /* 取得数据 */
    p_output = (char *)frmalloc(ui_length + 1);
    if (p_output == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    i_ret = bytebuff_get_bytes(p_st_data, p_output, ui_length);
    if (i_ret != FR_SUCC)
    {
        frfree(p_output);
        return APM_L7_ANALYZE_FAIL;
    }
    p_output[ui_length] = '\0';
    /* 跳过数据后的一位附加字节 */
    if (ui_end_word)
    {
        i_ret = bytebuff_skip(p_st_data, 1);
        if (i_ret != FR_SUCC)
        {
            frfree(p_output);
            return APM_L7_ANALYZE_FAIL;
        }
    }

    /* 设置出力返回 */
    *pp_output = p_output;
    *p_ui_out_size = ui_length + ui_end_word;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  跳过指定位数的数据
*  ARGS     :  p_st_data(bytebuff信息)
*           :  ui_length (要取得数据位的长度)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*           :  APM_L7_ANALYZE_TODO  (need more data)
*  NOTE     :
*******************************************************************************/
int informix_skip_bytes(Frbyte_Packet *p_st_data, unsigned int ui_length)
{
    /* 判断数据是长度否足够 */
    if (ui_length > (unsigned int)bytebuff_remaining(p_st_data))
    {
        return APM_L7_ANALYZE_TODO;
    }
    bytebuff_skip(p_st_data, ui_length);

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  跳过padded
*  ARGS     :  p_st_data(bytebuff信息)
*           :  i_whole_flg (packet数据包是否完整)
*           :  ui_length (要取得数据位的长度)
*           :  pp_output (出力数据内容)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*  RTN      :  APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int informix_skip_padded(Frbyte_Packet *p_st_data
                        , unsigned int ui_length)
{
    int i_ret = FR_SUCC;
    unsigned int ui_end_word = 0;

    /* 根据java反编译结合数据包, 假如长度位奇数则数据后有一位附加字节 */
    if (ui_length & 0x01)
    {
        ui_end_word = 1;
    }

    /* 判断数据是长度否足够 */
    if (ui_length + ui_end_word > (unsigned int)bytebuff_remaining(p_st_data))
    {
        return APM_L7_ANALYZE_TODO;
    }
    i_ret = bytebuff_skip(p_st_data, ui_length + ui_end_word);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  取得2bytes长度位padded
*  ARGS     :  p_st_data(bytebuff信息)
*           :  pp_output (出力数据内容)
*           :  p_ui_out_size (出力数据内容size)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*  RTN      :  APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int informix_get_2byte_padded(Frbyte_Packet *p_st_data
                             , char **pp_output
                             , unsigned int *p_ui_out_size)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    uint16_t u16_len = 0;

    /* 判断数据是长度否足够 */
    if (bytebuff_remaining(p_st_data) < 2)
    {
        return APM_L7_ANALYZE_TODO;
    }
    /* 取得长度 */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 跳过内容 */
    i_ret = informix_read_padded(p_st_data, u16_len, pp_output, p_ui_out_size);
    return i_ret;
}

/*******************************************************************************
*  FUNC     :  取得4bytes长度位padded
*  ARGS     :  p_st_data(bytebuff信息)
*           :  pp_output (出力数据内容)
*           :  p_ui_out_size (出力数据内容size)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*  RTN      :  APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int informix_get_4byte_padded(Frbyte_Packet *p_st_data
                             , char **pp_output
                             , unsigned int *p_ui_out_size)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    uint32_t u32_len = 0;

    /* 判断数据是长度否足够 */
    if (bytebuff_remaining(p_st_data) < 4)
    {
        return APM_L7_ANALYZE_TODO;
    }
    /* 取得长度 */
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_len, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 跳过内容 */
    i_ret = informix_read_padded(p_st_data, u32_len, pp_output, p_ui_out_size);
    return i_ret;
}

/*******************************************************************************
*  FUNC     :  跳过2bytes长度位padded
*  ARGS     :  p_st_data(bytebuff信息)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*  RTN      :  APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int informix_skip_2byte_padded(Frbyte_Packet *p_st_data)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    uint16_t u16_len = 0;

    /* 判断数据是长度否足够 */
    if (bytebuff_remaining(p_st_data) < 2)
    {
        return APM_L7_ANALYZE_TODO;
    }
    /* 取得长度 */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 跳过内容 */
    i_ret = informix_skip_padded(p_st_data, u16_len);
    return i_ret;
}

/*******************************************************************************
*  FUNC     :  跳过4bytes长度位padded
*  ARGS     :  p_st_data(bytebuff信息)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*  RTN      :  APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int informix_skip_4byte_padded(Frbyte_Packet *p_st_data)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    uint32_t u32_len = 0;

    /* 判断数据是长度否足够 */
    if (bytebuff_remaining(p_st_data) < 4)
    {
        return APM_L7_ANALYZE_TODO;
    }
    /* 取得长度 */
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_len, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 跳过内容 */
    i_ret = informix_skip_padded(p_st_data, u32_len);
    return i_ret;
}

/*******************************************************************************
*  FUNC     :  追加statement到hash中
*  ARGS     :  p_st_private (私有数据)
*  RTN      :  APM_L7_ANALYZE_SUCC
*              APM_L7_ANALYZE_FAIL
*  NOTE     :  p_st_private肯定不为NULL
*******************************************************************************/
int informix_add_statement(L7session_informix_private *p_st_private)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    Frlist_node *p_st_node = NULL;
    L7_req_informix *p_st_req = p_st_private->p_st_req;
    L7_resp_informix *p_st_resp = p_st_private->p_st_resp;

    /* 创建hash节点 */
    p_st_node = frlist_node_create(p_st_req->p_st_statement);
    if (p_st_node == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 删除原有的 */
    frhash2_delLong(p_st_private->p_hash_prepare
                   , p_st_resp->l_cursor_id
                   , frdb_statement_node_free);

    /* 追加现有的 */
    p_st_req->p_st_statement->st_metadata_column = p_st_resp->st_metadata_column;
    memset(&p_st_resp->st_metadata_column, 0x00, sizeof(p_st_resp->st_metadata_column));
    i_ret = frhash2_addLong(p_st_private->p_hash_prepare
                           , p_st_resp->l_cursor_id, p_st_node);
    if (i_ret != FR_SUCC)
    {
        frfree(p_st_node);
        frdbg("call frhash2_addLong failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }
    /* 出力设置 */
    p_st_req->i_new_statement = FR_NO;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  创建参数
*  ARGS     :  pp_st_value(参数值)
*  RTN      :  APM_L7_ANALYZE_FAIL      (FAIL)
*              APM_L7_ANALYZE_SUCC      (SUCC)
*  NOTE     :  pp_st_value必须不为NULL
*******************************************************************************/
void informix_free_param(Frdata_field **pp_st_value)
{
    if (pp_st_value == NULL || *pp_st_value == NULL)
    {
        return;
    }
    Frdata_field *p_st_value = *pp_st_value;

    if (p_st_value->p_field_value)
    {
        frfree(p_st_value->p_field_value);
    }
    if (p_st_value->p_field_name)
    {
        frfree(p_st_value->p_field_name);
    }
    frfree(p_st_value);
    *pp_st_value = NULL;
    return;
}


/*******************************************************************************
*  FUNC     :  跳过BLOB
*  ARGS     :  p_st_conn(入力链接信息)
*           :  p_st_private(私有session数据)
*  RTN      :  APM_L7_ANALYZE_FAIL      (FAIL)
*              APM_L7_ANALYZE_TODO      (More data)
*              APM_L7_ANALYZE_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int informix_parse_blob(Conntrack *p_st_conn
                        , L7session_informix_private *p_st_private)
{
    int i_ret = FR_SUCC;
    L7_fragment_informix *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    i_ret = informix_skip_2byte_padded(p_st_data);
    if (i_ret != APM_L7_ANALYZE_SUCC)
        frdbg("call informix_skip_2byte_padded failed!\n");

    return i_ret;
}
